home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-17 | 10.6 KB | 252 lines | [TEXT/MPS ] |
- ; Zap.a
- ;
- ; Copyright © 1991 by Apple Computer, Inc., all rights reserved.
- ;
- ; by Bo3b Johnson 1/10/91
- ; MS 37-DS
- ;
- ; This file is the assembly routines I need in order to interface to the toolbox in
- ; a sensible fashion. The OS is funky, and there is no good way to do these things
- ; from Pascal or C. The use of INLINE code is OK, but not always enough.
- ; Course I hate assembly language, since I tire of knives in the back, but there often
- ; is no alternative. Only dimwits think assembly is the way to go. Too bad so
- ; many people still have the Iron-Man syndrome, instead of using their brains.
- ;
- ; In order to fashion a good patch to NewPtr/NewHandle, I need to use PC
- ; relative addressing. The basic problem is that there is no good way to get back
- ; to the dcmd globals, while the patch is executing. Certainly you can't rely upon
- ; A5, A6, or A7; and no other registers are available for use. I could stick something
- ; into AppParms, CurApName, or a number of other atrocities, but I don't own
- ; any of those spots, and could quite easily end up competing with some other code
- ; for the spot. If I use PC-relative addressing to get to
- ; some global information, then this becomes self-modifying code, since I will
- ; change the code in this block, using a piece of code space as variable storage.
- ; This seems the most risk-free version for now, notwithstanding certain strident
- ; if misguided warnings from various groups. It's not enough to tell me not to
- ; do something, you have to give me an alternative. If you have a better alternative,
- ; by all means let me know.
- ;
- ; I patch the two traps of DisposPtr, DisposHandle; and these pieces are almost identical.
- ; The only difference really is the variable being
- ; used. The basic idea is to have one routine to save off the old address, gotten from
- ; an NGetTrapAddress; and to save that into the code here, using PC-relative addressing.
- ; The trap is patched by the Pascal code, and whenever it gets called, it will call here
- ; to have us call through the old version of the trap. That way it gets control before
- ; the trap executes, but I still drive the old code.
- ;
- ; Realize that the code in this file is getting run mostly during the normal operation
- ; of the Mac. The stack is whatever the current app is using, as well as that A5 world,
- ; and stack crawl. I don't know where I'll be so, I can't rely on those things. This
- ; is very different from the code in the dcmd, where it knows the stack it is using is
- ; in Macsbug, and very small. Pieces of this code will get run a tiny bit from the dcmd,
- ; since it will call here in order to get access to my global variables, the activeState.
- ;
- ; By the way, this file looks best if viewed in Palatino 12.
-
-
- include 'SysErr.a'
- include 'SysEqu.a'
- include 'Traps.a'
-
- proc
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ;
- ; Storage for the old patch addresses, used to call through once the patch code executes.
- ; These are essentially globals, used by the asm code. They are specifically not exported,
- ; so that the Pascal code cannot access them directly. There are a number of interface
- ; routines I set up so that Pascal can get and set them, but has to go through this file.
- ; You know, sort of object like.
- ;
- pOldDisposPtr dc.l 0
- pOldDisposHandle dc.l 0
-
- pActive dc.w 0 ; whether to watch blocks or not.
-
-
- saveEm reg a0-a3/d0-d3 ; a few to keep, since I'm a patch.
- saveEmSize EQU (8*4) ; 8 registers times 4 bytes each.
-
-
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ; When I'm am setting up the world, I call NGetTrapAddress to get the old version
- ; of the traps. I need to save that dude off so I can get back there when needed.
- ; This routine is a handy interface to the high-level world, isolating this asm junk
- ; from the code. All these routines are the same, just a different variable being affected.
- ; This hunk uses the PC-Relative addressing mode in order to get the address of the
- ; variable being set. This allows the code to function without any explicit global
- ; space, since the code acts like globals here.
- ; The interface is:
- ; PROCEDURE SetOldDisposPtr (address: LongInt);
- ; PROCEDURE SetOldDisposHandle (address: LongInt);
-
- export SetOldDisposPtr, SetOldDisposHandle
-
- SetOldDisposPtr
- LEA pOldDisposPtr,A1 ; the variable to do
- BRA.S Common ; do common stuffing code.
- SetOldDisposHandle
- LEA pOldDisposHandle,A1 ; the variable
- Common
- MOVE.L (SP)+,A0 ; get the return address.
- MOVE.L (SP)+,(A1) ; save it, pulling parameter too.
- JMP (A0) ; it's saved, return to high-level.
-
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ; Killt fer now.
- ; FUNCTION TrackActive: Boolean; EXTERNAL;
-
-
- ; TrackActive:
- ; Just return the active state as a boolean. This is whether I am actively watching
- ; and recording block addresses or not. I always want to be able to turn it off sometimes,
- ; since I want to save a given state for viewing.
- ; FUNCTION TrackActive: Boolean; EXTERNAL;
-
- ;TrackActive
- ; MOVE.W pActive,4(SP) ; stuff function result (pc-relative source).
- ; RTS ; and return to caller.
-
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ; As part of the interface to the dcmd, I have setting routines too, to set the variables
- ; to a known state. This way I don't have to put that sort of tree-based init code in
- ; assembly. I need to turn it on and off using the dcmd, so it will call here to do so.
- ;
- ; PROCEDURE SetActive (state: Boolean); EXTERNAL;
-
-
- export SetActive
-
- ; PROCEDURE SetActive (state: Boolean); EXTERNAL;
-
- SetActive
- MOVE.L (SP)+,A0 ; the return address, for safe keeping.
- LEA pActive,A1 ; the variable I need to set, pc-relative.
- MOVE.W (SP)+,(A1) ; save off the new state, clearing parameter.
- JMP (A0) ; and return to caller.
-
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ; This is the patch code for the various pieces I patch. This is in assembly
- ; since I need to preserve registers and do some other low level jacking around.
- ; These routines are the specific code that gets called when one of the four traps is executed.
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ; WatchDisposPtr:
- ; This routine is my patch to DisposPtr. I will get the size of the block, then have the block
- ; stuffed into all blow up numbers. This is a head patch, since I do my thing, then jump to
- ; the old routine. When that routine finishes, it will call RTS and go back to
- ; wherever I was called from.
-
- export WatchDisposPtr
-
- WatchDisposPtr
- MOVEM.L saveEm,-(SP) ; save registers in trap patches.
-
- MOVE.W pActive,D0 ; is it turned on to watch?
- BEQ.S CallOldDisposePtr ; if not, skip saving.
-
- _GetPtrSize ; find out how big the dude is.
- TST.L D0 ; if it is not a real thing?
- BLE.S CallOldDisposePtr ; negative or zero, skip the stomp.
-
- MOVE.L A0,-(SP) ; block being killed, save it's address.
- MOVE.L D0,-(SP) ; size of the block.
-
- BSR.S StompBlock ; go turn it into mush.
-
- CallOldDisposePtr
- MOVEM.L (SP)+,saveEm ; save registers in trap patches.
-
- MOVE.L pOldDisposPtr,-(SP) ; get address of old routine.
- RTS ; and jump there.
- ; when it RTSes, I'll go back to the caller.
-
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ; WatchDisposHandle:
- ; This routine is my patch to DisposHandle. I get the size of the block, then call StompBlock
- ; to turn it into all trashed numbers. This is a head patch, since I do my thing, then jump to
- ; the old routine. When that routine finishes, it will call RTS and go back to
- ; wherever I was called from.
-
- export WatchDisposHandle
-
- WatchDisposHandle
- MOVEM.L saveEm,-(SP) ; save registers in trap patches.
-
- MOVE.W pActive,D0 ; is it turned on to watch?
- BEQ.S CallOldDisposeHandle ; if not, skip saving.
-
- _GetHandleSize ; find out how big the handle is.
- TST.L D0 ; Test to see what happened.
- BLE.S CallOldDisposeHandle ; negative or zero, skip the stomp.
-
- MOVE.L (A0),-(SP) ; dereference handle to pointer, as block.
- MOVE.L D0,-(SP) ; pass the size to kill
-
- BSR.S StompBlock ; and turn it into mush.
-
- CallOldDisposeHandle
- MOVEM.L (SP)+,saveEm ; save registers in trap patches.
-
- MOVE.L pOldDisposHandle,-(SP) ; get address of old routine.
- RTS ; and jump there.
- ; when it RTSes, I'll go back to the caller.
-
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
- ;
- ; StompBlock:
- ; This is the key routine to the entire thing. It will stuff a blow up number into the block as a
- ; repeating pattern of long words. Right now I whap on the full long words, including the
- ; correction bytes the memory manager sets aside for things not divisible by 4. This assumes
- ; that it won't get passed a zero length object.
- ;
- ; It trashes no registers.
- ;
- ; Procedure StompBlock (block: Ptr; size: LongInt);
-
- zapValue EQU $50FFC001 ; funky bus error number.
-
-
- StompBlock
- MOVEM.L A0/D0,-(SP) ; save registers we kill.
-
- MOVE.L 16(SP),A0 ; address of block to stuff. *** use record.
- MOVE.L 12(SP),D0 ; length of block.
-
- ; If we got passed a zero for the pointer, something is wrong.
-
- CMP.L #0,A0 ; is it nice?
- BNE.S @1 ; if so go ahead.
- PEA #'Nil block to Zap'
- _DebugStr ; else yell about it.
- @1
- ; Find out how big the block is, in LongInt counts. Loop for that many times, stuffing the
- ; LongInt number into the buffer. I round up to the nearest long word, since the size correction
- ; will always be used on Mac II class machines. This will make it work for 0 length blocks too.
- ; Can't use DBRA count, since that can't handle big enough blocks.
-
- ADDQ.L #3,D0 ; round up to nearest longword.
- LSR.L #2,D0 ; divide by 4, giving Long word count.
- @0
- MOVE.L #zapValue,(A0)+ ; stuff the killer number
- SUBQ.L #1,D0 ; decrement count.
- BGT.S @0 ; if more to do, go back.
-
-
- MOVEM.L (SP)+,A0/D0 ; restore registers.
- MOVE.L (SP)+,(SP) ; push return address over parameter
- MOVE.L (SP)+,(SP) ; push return address over parameter, twice.
- RTS
-
- endproc
-
- ; ——————————————————————————————————————————————————————————————————————————————————————————————————
-
- end
-